/*
 * 文件名：EmptyTools.java
 * 版权：MoonBox 
 * 修改人：Peter
 * 修改时间：2018年10月10日
 * 修改内容：新增
 */
package com.renzhebiao.lkang.utils;

import java.lang.reflect.Array;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.math.BigDecimal;
import java.util.Collection;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.Map;

/**
 * <p>
 * 判null
 * 
 * @author Peter
 * @since 1.0.0
 */
public class EmptyTools {

    /**
     * 字符串为空或者null判断
     * 
     * @param str str
     * @return null判断
     */
    public static boolean isNull(String str) {
        return str == null || str.isEmpty();
    }

    /**
     * 字符串为空字符串判断
     * 
     * @param str str
     * @return true:是空字符串""，false:不为空或者为null
     */
    public static boolean isEmpty(String str) {
        return str != null && str.isEmpty();
    }

    /**
     * 集合为空判断
     * 
     * @param v str str
     * @return null判断
     */
    public static boolean isNull(Collection<?> v) {
        return v == null || v.isEmpty();
    }

    /**
     * MAP为空判断
     * 
     * @param v str str
     * @return null判断
     */
    public static boolean isNull(Map<?, ?> v) {
        return v == null || v.isEmpty();
    }

    /**
     * Array为空判断
     * 
     * @param v str str
     * @return null判断
     */
    public static boolean isNull(Object[] v) {
        return v == null || v.length == 0;
    }

    /**
     * 字符串不为空判断
     * 
     * @param str v
     * @return null判断
     */
    public static boolean notNull(String str) {
        return !isNull(str);
    }

    /**
     * 数字为空判断
     * 
     * @param v str str
     * @return null判断
     */
    public static boolean isNull(Number v) {
        return v == null || v.intValue() == 0;
    }

    /**
     * BigDecimal为空判断
     * 
     * @param v v
     * @return null判断
     */
    public static boolean notNull(BigDecimal v) {
        return v != null && v.compareTo(new BigDecimal(0)) > 0;
    }

    /**
     * BigDecimal为空判断
     * 
     * @param v v
     * @return null判断
     */
    public static boolean isNull(BigDecimal v) {
        return !notNull(v);
    }

    /**
     * 数字为空判断
     * 
     * @param n v
     * @return null判断
     */
    public static boolean notNull(Number n) {
        return !isNull(n);
    }

    /**
     * 集合不为空判断
     * 
     * @param v str
     * @return null判断
     */
    public static boolean notNull(Collection<?> v) {
        return !isNull(v);
    }

    /**
     * MAP不为空判断
     * 
     * @param v str
     * @return null判断
     */
    public static boolean notNull(Map<?, ?> v) {
        return !isNull(v);
    }

    /**
     * array不为空判断
     * 
     * @param v str
     * @return null判断
     */
    public static boolean notNull(Object[] v) {
        return !isNull(v);
    }

    /**
     * 反射，方法没有参数判断
     * 
     * @param m v
     * @return null判断
     */
    public static boolean notPram(Method m) {
        return m.getParameterTypes().length == 0;
    }

    /**
     * 方法不是静态的判断
     * 
     * @param m v
     * @return null判断
     */
    public static boolean notStatic(Method m) {
        int mo = m.getModifiers();
        return !Modifier.isStatic(mo);
    }

    /**
     * 数组为空判断
     * 
     * @param data data
     * @return null判断
     */
    public static boolean isNull(byte[] data) {
        return data == null || data.length == 0;
    }

    /**
     * Array为空判断
     * 
     * @param v str str
     * @return null判断
     */
    public static boolean isNull(Object v) {
        return v == null;
    }

    public static final boolean notNull(Object v) {
        return !isNull(v);
    }

    // ----------Number greater than
    public static final boolean gt(Long v) {
        return gt(v, 0L);
    }

    public static final boolean gt(Long v, Long t) {
        if (v == null || t == null) {
            return false;
        }
        return v > t;
    }

    // ----------equals

    /**
     * equalsTrue
     * 
     * @param value value
     * @return boolean
     */
    public static boolean equalsTrue(String value) {
        return "true".equals(value);
    }

    /**
     * <p>
     * Checks if a CharSequence is empty (""), null or whitespace only.
     * </p>
     * <p>
     * Whitespace is defined by {@link Character#isWhitespace(char)}.
     * </p>
     *
     * <pre>
     * Asserts.isBlank(null)      = true
     * Asserts.isBlank("")        = true
     * Asserts.isBlank(" ")       = true
     * Asserts.isBlank("bob")     = false
     * Asserts.isBlank("  bob  ") = false
     * </pre>
     *
     * @param cs the CharSequence to check, may be null
     * @return {@code true} if the CharSequence is null, empty or whitespace only
     * @since 2.0
     * @since 3.0 Changed signature from isBlank(String) to isBlank(CharSequence)
     */
    public static boolean isBlank(final CharSequence cs) {
        int strLen;
        if (cs == null || (strLen = cs.length()) == 0) {
            return true;
        }
        for (int i = 0; i < strLen; i++) {
            if (Character.isWhitespace(cs.charAt(i)) == false) {
                return false;
            }
        }
        return true;
    }

    /**
     * 判断对象 <code>value</code> 是不是 null或者empty.
     * <h3>示例:</h3> <blockquote>
     * 
     * <pre class="code">
     * 
     * <span style="color:green">// null</span>
     * Asserts.isNullOrEmpty(null)                                            = true
     * 
     * <span style="color:green">//CharSequence</span>
     * Asserts.isNullOrEmpty("")                                              = true
     * Asserts.isNullOrEmpty("   ")                                           = true
     * 
     * Asserts.isNullOrEmpty(new StringBuffer())                              = true
     * Asserts.isNullOrEmpty(new StringBuffer(""))                            = true
     * Asserts.isNullOrEmpty(new StringBuffer(" "))                           = true
     * 
     * Asserts.isNullOrEmpty(new StringBuilder())                             = true
     * Asserts.isNullOrEmpty(new StringBuilder(""))                           = true
     * Asserts.isNullOrEmpty(new StringBuilder(" "))                          = true
     * 
     * <span style="color:green">//Collection</span>
     * Asserts.isNullOrEmpty(new ArrayList{@code <String>}())                 = true
     * 
     * <span style="color:green">//Map</span>
     * Asserts.isNullOrEmpty(new LinkedHashMap{@code <String, String>}())     = true
     * 
     * <span style="color:green">//Iterator</span>
     * Asserts.isNullOrEmpty(new ArrayList{@code <String>}().iterator())      = true
     * 
     * <span style="color:green">//Enumeration</span>
     * Asserts.isNullOrEmpty(toEnumeration(new ArrayList{@code <String>}()))  = true
     * 
     * <span style="color:green">//Array</span>
     * Asserts.isNullOrEmpty(new String[] {})                                 = true
     * Asserts.isNullOrEmpty(new Integer[][] {})                              = true
     * Asserts.isNullOrEmpty(new User[] {})                                   = true
     * 
     * <span style="color:green">//Primitive Array</span>
     * Asserts.isNullOrEmpty(new double[] {})                                 = true
     * Asserts.isNullOrEmpty(new float[] {})                                  = true
     * Asserts.isNullOrEmpty(new long[] {})                                   = true
     * Asserts.isNullOrEmpty(new int[] {})                                    = true
     * Asserts.isNullOrEmpty(new short[] {})                                  = true
     * Asserts.isNullOrEmpty(new char[] {})                                   = true
     * Asserts.isNullOrEmpty(new byte[] {})                                   = true
     * Asserts.isNullOrEmpty(new boolean[] {})                                = true
     * </pre>
     * 
     * </blockquote>
     * <h3>对于empty的判断,使用以下逻辑:</h3> <blockquote>
     * <ol>
     * <li>{@link CharSequence},支持子类有 {@link String},{@link StringBuffer},{@link StringBuilder},使用
     * {@link org.apache.commons.lang3.StringUtils#isBlank(CharSequence)};</li>
     * <li>{@link Collection},使用其 {@link Collection#isEmpty()};</li>
     * <li>{@link Map},使用其 {@link Map#isEmpty()};</li>
     * <li>{@link Enumeration},使用 {@link Enumeration#hasMoreElements()};</li>
     * <li>{@link Iterator},使用 {@link Iterator#hasNext()};</li>
     * <li><code>数组</code>{@link java.lang.Class#isArray()},判断 {@link Array#getLength(Object)} ==0</li>
     * </ol>
     * </blockquote>
     * 
     * @param value
     * 可以是{@link Collection},{@link Map},{@link Enumeration},{@link Iterator},{@link Iterable},{@link CharSequence},
     * 以及所有数组类型(包括原始类型数组)
     * @return 如果是null,返回true<br>
     * 如果是empty也返回true<br>
     * 其他情况返回false<br>
     * @see org.apache.commons.collections4.CollectionUtils#sizeIsEmpty(Object)
     * @see org.apache.commons.lang3.StringUtils#isBlank(CharSequence)
     */
    public static boolean isNullOrEmpty(Object value) {
        if (null == value) {
            return true;
        }
        // 字符串
        if (value instanceof CharSequence) {
            return EmptyTools.isBlank((CharSequence) value);
        }

        // collections 支持的类型
        if (isCollectionsSupportType(value)) {
            return Collections.sizeIsEmpty(value);
        }
        return false;
    }

    /**
     * 判断对象 <code>value</code> 是否不是null或者empty,调用 !{@link #isNullOrEmpty(Object)} 方法 .
     * <p>
     * 示例参考 {@link #isNullOrEmpty(Object)} 方法
     * </p>
     * <h3>对于empty的判断,使用以下逻辑:</h3> <blockquote>
     * <ol>
     * <li>{@link CharSequence},支持子类有 {@link String},{@link StringBuffer},{@link StringBuilder},使用
     * {@link org.apache.commons.lang3.StringUtils#isBlank(CharSequence)};</li>
     * <li>{@link Collection},使用其 {@link Collection#isEmpty()};</li>
     * <li>{@link Map},使用其 {@link Map#isEmpty()};</li>
     * <li>{@link Enumeration},使用 {@link Enumeration#hasMoreElements()};</li>
     * <li>{@link Iterator},使用 {@link Iterator#hasNext()};</li>
     * <li><code>数组</code>{@link java.lang.Class#isArray()},判断 {@link Array#getLength(Object)} ==0</li>
     * </ol>
     * </blockquote>
     * 
     * @param value
     * 可以是{@link Collection},{@link Map},{@link Enumeration},{@link Iterator},{@link Iterable},{@link CharSequence}
     * ,以及所有数组类型(包括原始类型数组)
     * @return 如果是null,返回false<br>
     * 如果是空也返回false<br>
     * 其他情况返回true<br>
     * @see #isNullOrEmpty(Object)
     */
    public static boolean isNotNullOrEmpty(Object value) {
        return !isNullOrEmpty(value);
    }

    /**
     * Checks if is collections support type.
     *
     * @param value the value
     * @return true, if checks if is collections support type
     * @since 1.5.2
     */
    private static boolean isCollectionsSupportType(Object value) {
        // 集合或者map
        boolean isCollectionOrMap = value instanceof Collection || value instanceof Map;

        // 枚举 或者是 Iterator迭代器
        boolean isEnumerationOrIterator = value instanceof Enumeration || value instanceof Iterator;

        return isCollectionOrMap// 集合或者map
               || isEnumerationOrIterator// 枚举 或者是 Iterator迭代器
               || value.getClass().isArray()// 判断数组
        ;
    }

}
